def print_info(name, age, addr="北京"):
    """打印个人信息
    
    :param name: 姓名
    :param age: 年龄
    :param addr: 地址
    """
    print(f"我叫{name}, 今年{age}岁, 来自{addr}")

def print_hobbies(name, *hobbies):
    """打印个人爱好
    
    :param name: 姓名
    :param hobbies: 可变参数，表示多个爱好
    """
    print(f"{name}的爱好有:",end="")
    for hobby in hobbies:
        print(f"- {hobby}",end="\t")

def print_family_info(name, **family_members):
    """打印家庭成员信息
    
    :param name: 姓名
    :param family_members: 可变关键字参数，表示家庭成员信息
    """
    print(f"{name}的家庭成员:",end="")
    for relation, member_name in family_members.items():
        print(f"{relation}: {member_name}",end="\t")

# 1. 位置参数:在函数调用时，按照函数定义时的参数顺序来传递参数
print_info("小刚", 18, "上海")

# 2. 关键字参数:在函数调用时，通过"参数名=值"的形式来指定参数值，这样就不需要按照函数定义时的参数顺序来传递参数
print_info(addr="上海", age=18, name="小刚")

# 3. 混合参数:关键字参数可以和位置参数结合使用，但位置参数必须在前，而且顺序一致
print_info("小刚", addr="上海", age=18)

# 4. 默认参数:在函数定义时，为参数指定默认值，调用时，如果没有传递参数值，则会使用默认参数
# 默认参数要在位置参数之后，否则会引发语法错误
print_info("小刚",18)

# 5. 可变参数(*args):允许函数接受任意数量的位置参数，以元组形式传入
print_hobbies("小明", "游泳", "跑步", "看电影")
print()

# 6. 可变关键字参数(**kwargs):允许函数接受任意数量的关键字参数，以字典形式传入
print_family_info("小红", father="张三", mother="李四", sister="张小妹")
print()

# 7.函数作为参数传递
def sum(a,b):
    return a + b
def func(sum):
    print(sum(1,2))
func(sum)#不需要加括号，以为加了括号就是函数的调用